package org.jdcenter.server.deployment;

import java.util.List;

import net.sf.cglib.proxy.Enhancer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdcenter.Constants;
import org.jdcenter.server.xb.metadata.BeanMateData;
import org.jdcenter.server.xb.metadata.MateData;
import org.jdcenter.server.xb.metadata.ParameterMateData;

import org.jdstream.picocontainer.PluginsPicoContainer;
import org.picocontainer.Characteristics;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.Parameter;

public class BeanDeployer implements AbstractDeployer{
	private Log log = LogFactory.getLog(getClass());
	private PluginsPicoContainer pico;
	private BeanMateData bData;
	
	public BeanDeployer(PluginsPicoContainer pico,BeanMateData bData){
		this.pico = pico;
		this.bData = bData;
	}

	@Override
	public void deploy(MateData mateData) {
		
		if(!(mateData instanceof BeanMateData)){
			throw new DeployException("mateData must be BeanDeployer");
		}
		if(pico == null){
			throw new DeployException("MutablePicoContainer can not be null");
		}
		this.bData = (BeanMateData)bData;
		deploy();
	}


	@Override
	public void deploy() {
		log.info("start deploy beans");
		if(pico == null || bData == null){
			return;
		}
		if(isLife()){
			register(bData.getBeanName()+Constants.proxySuffix);
			
			BeanInterceptor interceptor = new BeanInterceptor(bData,
					pico.getComponent(bData.getBeanName()+Constants.proxySuffix));
			
            Enhancer e = new Enhancer();
            e.setSuperclass(BeanAdaptor.class);
            e.setSuperclass(bData.getClazz());
            e.setCallback(interceptor);
            Object bean = e.create();
            pico.addComponent(bData.getBeanName(),bean);
		}else{
			register(bData.getBeanName());
		}
		
	}
	
	@Override
	public void undeploy() {
		log.info("start undeploy beans");
		pico.stop();
		pico.removeComponents();
	}
	
	private boolean isLife(){
		return bData.getStartName() != null 
			|| bData.getStopName() != null
			|| bData.getDisposeName() != null; 
	}
	
	private void register(String name){
		boolean isSetter = false;
		if(bData.getConstructorParameters() == null 
				&& bData.getSetterParameters() != null){
			pico.change(Characteristics.SDI);
			isSetter = true;
		}
		pico.addComponent(name,bData.getClazz(),getParameter(isSetter));		
	}
	
	private Parameter[] getParameter(boolean isSetter){
		List<ParameterMateData> parameters = null;
		if(isSetter){
			parameters = bData.getSetterParameters();
		}else{
			parameters = bData.getConstructorParameters();
		}
		if(parameters == null || parameters.size() == 0){
			return new Parameter[0];
		}
		Parameter[] parameter = new Parameter[parameters.size()];
		for(int i=0;i<parameters.size();i++){
			parameter[i] = parameters.get(i).getParameter();
		}
		return parameter;
	}

	
	

}
